/* NeXtInterface.m */
/* Written by : Jason R. Wilson   2/21/93 */

/* this package (along with CView) provides a NeXtStep interface
    for NeXtRad */

#import <appkit/Application.h>
#import <appkit/Window.h>
#import "CView.h"
#import <appkit/Menu.h>
#import <appkit/MenuCell.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/graphics.h>
#import <stdlib.h>
#import <stdio.h>
#import "NeXtInterface.h"
#import "engine.h"
#import <appkit/Button.h>
#import <appkit/ButtonCell.h>

char SceneFileName[256]; /* the name of the scene file */
id myWindow, myView, myMenu, myImage, myButtonCellf, myButtonf,myButtonCellb,myButtonb;
id myButtonCelll,myButtonl,myButtonCellr,myButtonr,myButtonCellu,myButtonu,myButtonCelld,myButtond;
id myButtonCellfast,myButtonfast,myButtonCellslow,myButtonslow;
/* id myOutputImage; */
unsigned char *ScreenBuf;
/* unsigned char *OutputBuf; */
NXRect graphicsRect;
/* NXRect outputRect; */
NXRect buttonRectf,buttonRectb,buttonRectl,buttonRectr,buttonRectu,buttonRectd,buttonRectfast,buttonRectslow;

void SetWidth (int width)
{
  winWidth = width;
}

void SetHeight (int height)
{
  winHeight = height;
}


void InitGraphics ()
{

  /* create the scene window */
  
  NXSetRect(&graphicsRect,100.0,300.0,(NXCoord)winWidth+100,(NXCoord)winHeight);
  myWindow = [[Window alloc] initContent:&graphicsRect
	    style:NX_TITLEDSTYLE
	    backing:NX_BUFFERED
	    buttonMask:NX_MINIATURIZEBUTTONMASK
	    defer:NO];
  [myWindow setTitle:SceneFileName];
  [myWindow display];
  
  /* create the object to store and display the bitmap */
  
  myImage =  [[NXBitmapImageRep alloc]	initData:ScreenBuf
	    pixelsWide:winWidth
	    pixelsHigh:winHeight
	    bitsPerSample:8
	    samplesPerPixel:3
	    hasAlpha:NO
	    isPlanar:NO
	    colorSpace:2
	    bytesPerRow:winWidth*3
	    bitsPerPixel:24];
  
  /* draw the bitmap */
  
  [myImage draw];
  
  /* set up the view object (an instance of CView) */
  
  myView = [[CView alloc] initFrame:&graphicsRect];
  
  /* set up the buttons */
  
  NXSetRect(&buttonRectf,(NXCoord)winWidth+40,(NXCoord)winHeight-100,20,20);  
  myButtonf = [[Button alloc] initFrame:&buttonRectf
               title:"F"
 	       tag:1
               target:myView
               action:@selector(forward:)
	       key:0
 	       enabled:YES];
  [myView addSubview:myButtonf];
  myButtonCellf = [[ButtonCell alloc] initTextCell:"F"];
  [myButtonCellf drawSelf:&buttonRectf
                inView:myView];

  NXSetRect(&buttonRectb,(NXCoord)winWidth+40,(NXCoord)winHeight-140,20,20);
  myButtonb = [[Button alloc] initFrame:&buttonRectb
	       title:"B"
               tag:2
               target:myView
               action:@selector(backward:)
               key:0
               enabled:YES];
  [myView addSubview:myButtonb];
  myButtonCellb = [[ButtonCell alloc] initTextCell:"B"];
  [myButtonCellb drawSelf:&buttonRectb
 	 	inView:myView];

  NXSetRect(&buttonRectl,(NXCoord)winWidth+20,(NXCoord)winHeight-120,20,20);
  myButtonl = [[Button alloc] initFrame:&buttonRectl
	       title:"L"
               tag:3
               target:myView
               action:@selector(turnleft:)
               key:0
               enabled:YES];
  [myView addSubview:myButtonl];
  myButtonCelll = [[ButtonCell alloc] initTextCell:"L"];
  [myButtonCelll drawSelf:&buttonRectl
 	 	inView:myView];

  NXSetRect(&buttonRectr,(NXCoord)winWidth+60,(NXCoord)winHeight-120,20,20);
  myButtonr = [[Button alloc] initFrame:&buttonRectr
	       title:"R"
               tag:4
               target:myView
               action:@selector(turnright:)
               key:0
               enabled:YES];
  [myView addSubview:myButtonr];
  myButtonCellr = [[ButtonCell alloc] initTextCell:"R"];
  [myButtonCellr drawSelf:&buttonRectr
 	 	inView:myView];

  NXSetRect(&buttonRectu,(NXCoord)winWidth+40,(NXCoord)winHeight-200,20,20);
  myButtonu = [[Button alloc] initFrame:&buttonRectu
	       title:"U"
               tag:5
               target:myView
               action:@selector(tiltup:)
               key:0
               enabled:YES];
  [myView addSubview:myButtonu];
  myButtonCellu = [[ButtonCell alloc] initTextCell:"U"];
  [myButtonCellu drawSelf:&buttonRectu
 	 	inView:myView];

  NXSetRect(&buttonRectd,(NXCoord)winWidth+40,(NXCoord)winHeight-240,20,20);
  myButtond = [[Button alloc] initFrame:&buttonRectd
	       title:"D"
               tag:6
               target:myView
               action:@selector(tiltdown:)
               key:0
               enabled:YES];
  [myView addSubview:myButtond];
  myButtonCelld = [[ButtonCell alloc] initTextCell:"D"];
  [myButtonCelld drawSelf:&buttonRectd
 	 	inView:myView];

  NXSetRect(&buttonRectfast,(NXCoord)winWidth+20,(NXCoord)winHeight-320,60,20);
  myButtonfast = [[Button alloc] initFrame:&buttonRectfast
                   title:"Faster"
	           tag:7
	           target:myView
	           action:@selector(movefaster:)
	           key:0
                   enabled:YES];
  [myView addSubview:myButtonfast];
  myButtonCellfast = [[ButtonCell alloc] initTextCell:"Faster"];
  [myButtonCellfast drawSelf:&buttonRectfast
		inView:myView];


  NXSetRect(&buttonRectslow,(NXCoord)winWidth+20,(NXCoord)winHeight-360,60,20);
  myButtonslow = [[Button alloc] initFrame:&buttonRectslow
                   title:"Slower"
	           tag:8
	           target:myView
	           action:@selector(moveslower:)
	           key:0
                   enabled:YES];
  [myView addSubview:myButtonslow];
  myButtonCellslow = [[ButtonCell alloc] initTextCell:"Slower"];
  [myButtonCellslow drawSelf:&buttonRectslow
		inView:myView];


  [myView setOpaque:YES];
  [myWindow setContentView:myView];
  [myWindow makeKeyAndOrderFront:nil];			  
  /* set up the menus */
  
  myMenu = [[Menu alloc] initTitle:"NeXtRad"];
  [[myMenu addItem:"clear" action:@selector(clear:) keyEquivalent:'k']
   setTarget:myView];
  [[myMenu addItem:"wireframe" action:@selector(wireframe:) keyEquivalent:'w']
   setTarget:myView];
  [[myMenu addItem:"render" action:@selector(refresh:) keyEquivalent:'r']
   setTarget:myView];
  [[myMenu addItem:"subdivide" action:@selector(subdivide:) keyEquivalent:'s']
   setTarget:myView];
  [[myMenu addItem:"outputPPM" action:@selector(outputPPM:) keyEquivalent:'o']
   setTarget:myView];
  [myMenu addItem:"Quit" action:@selector(terminate:)
    keyEquivalent:'q'];
  [myMenu sizeToFit];
  [NXApp setMainMenu:myMenu];



}

void OutputPPM ()
/* write current view area to a .ppm file */

{
  FILE *ppmfp;
  char filename[256];
  int loop,loop2;
  int address;
  /* for some reason, the code that is commentted out only works
     on the NeXTDimension ??? */
/*  [myView lockFocus]; */
/*  NXSetRect(&outputRect,0.0,0.0,(NXCoord)winWidth,(NXCoord)winHeight); */
/*  OutputBuf = NULL; */
/*  myOutputImage = [[NXBitmapImageRep alloc]  initData:OutputBuf
    fromRect:&outputRect];    load data into OutputBuf */
/*  OutputBuf = [myOutputImage data]; */
  printf ("Please enter the name of the ppm file that you wish to output:\n");
  scanf ("%s",filename);
  ppmfp = fopen (filename,"w"); /* open ppm output file */
  printf ("writing .ppm file ...\n");
  /* write .ppm file */
  fprintf (ppmfp,"%s\n","P6");  
  fprintf (ppmfp,"%d %d\n",winWidth,winHeight);
  fprintf (ppmfp,"%d\n",255);
  for (loop = 0;loop < winHeight;loop++)
     for (loop2 = 0;loop2 < winWidth;loop2++)
       {
         address = 3*(loop2 + winWidth*loop);
         fprintf (ppmfp,"%c%c%c",ScreenBuf[address],
 			         ScreenBuf[address+1],
                                 ScreenBuf[address+2]);
       }
  close (ppmfp);
/*  [myOutputImage free]; */
  printf ("Finished writing .ppm file\n");
/*  [myView unlockFocus]; */
}

/***********************************************************************/


void SetPixel (int x, int y,unsigned char r,unsigned char g,unsigned char b)
/* update a particular pixel in ScreenBuf */
{
  int address;
  address = 3*(x + winWidth*y);
  ScreenBuf[address] = r;
  ScreenBuf[address+1] = g;
  ScreenBuf[address+2] = b;
}

void Update (void)
/* redraw the view area */
{
  [myView lockFocus];
  [myImage draw];
  PSflushgraphics(); 
  [myView unlockFocus];
}

void DrawButtons (void)
{
/* redraw the buttons */

  [myButtonCellf drawSelf:&buttonRectf
    inView:myView];
  [myButtonCellb drawSelf:&buttonRectb
    inView:myView];
  [myButtonCelll drawSelf:&buttonRectl
    inView:myView];
  [myButtonCellr drawSelf:&buttonRectr
    inView:myView];
  [myButtonCellu drawSelf:&buttonRectu
    inView:myView];	  
  [myButtonCelld drawSelf:&buttonRectd
    inView:myView];
  [myButtonCellfast drawSelf:&buttonRectfast
    inView:myView];
  [myButtonCellslow drawSelf:&buttonRectslow
    inView:myView];
}

/***********************************************************************/

void main (void)
/* set-up and start event loop rolling */
{
  [Application new];
  SetWidth (640);
  SetHeight (480);
  ScreenBuf = (unsigned char *)(malloc(winWidth*winHeight*3)); 
  engine(SceneFileName);
  InitGraphics(); 
  [NXApp run];
  [NXApp free];
}
    

